﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Gp.Scripts.Core.Res;
using Gp.Scripts.GameLogic;
using Gp.Scripts.GUI;
using QFramework;
using Sirenix.OdinInspector;
using UnityEngine;

namespace Gp.Scripts.Core
{
    public class BattleSettleRoot : SettleNodeRoot
    {
        #if UNITY_EDITOR
        /// <summary>
        /// 是否为战斗模拟，如果为true，则会在初始化时尝试开始战斗
        /// </summary>
        [LabelText("战斗模拟器")]
        [SerializeField] private bool isBattleSimulation = false;
        #endif

        private Dictionary<string, BaseUnit> _unitMap;

        public bool IsBattleStarting { get; private set; }

        public ITurnResolver TurnResolveController { get; private set; }

        public BattleCellGrid BattleCellGrid { get; private set; } 
        
        public BaseUnit CurrentUnit
        {
            get
            {
                if (GameState is GameStateUnitSelect unitPlayState)
                {
                    return unitPlayState.CurrentUnit;
                }

                return null;
            }
        }

        private BattlePlayer _player;

        public BattlePlayer CurrentPlayer
        {
            get => _player;
            set
            {
                value.Play();
                _player = value;
            }
        }

        public List<BattlePlayer> Players { get; set; }
        public HumanPlayer HumanPlayer { get; private set; }
        
        public BattleUI3DNode BattleUI3DNode { get; private set; }
        public EventHandler EventHandler = new();
        private Res.ResLoader _resLoader;
        
        #region Data Handle

        protected override void OnInit()
        {
            #if UNITY_EDITOR
            if (this.isBattleSimulation)
            {
                Global.RegisterEvent<Event_System.GameStart>(args =>
                {
                    Global.Get<BattleSystem>().StartBattle();
                });
            }
            #endif

            Global.RegisterEvent<Event_System.GameStart>(args =>
            {
                _resLoader = ResLoader.Allocate();
                const string feedbackNodeName = "FeedbackPlayer";
                if (transform.Find(feedbackNodeName))
                {
                    return;
                }
                var feedBackPlayer = _resLoader.LoadSync<FeedBackPlayer>(ConstBundle.BASIC, feedbackNodeName).InstantiateWithParent(transform);
                feedBackPlayer.name = feedbackNodeName;
            }).UnRegisterWhenGameObjectDestroyed(gameObject);
        }

        public void BattleStart()
        {
            if (IsBattleStarting) return;
            
            _unitMap       = new Dictionary<string, BaseUnit>();
            BattleCellGrid = new BattleCellGrid();
            BattleCellGrid.InitGrid(transform);
            
            

            // 发送战斗开始事件
            Global.SendEvent(new Event_BattleInit());
            IsBattleStarting = true;
            // 单位初始化
            InitUnitsProcess();
            
            // 关卡初始化
            InitSettleProcess();

            var trans = this.GetOrCreate<BattleCameraTarget>("BattleCameraTarget").transform;
            Global.GetSceneRoot<PlayerRoot>().CameraFlowPivot.transform.position = trans.position;
            EventHandler.RegisterEvent<Event_Unit.Select>(args =>
            {
                Global.GetSceneRoot<PlayerRoot>().CameraFlowPivot.MainFollowTarget = args.Unit.transform;
            });
            
            // 发送初始化完成事件
            Global.SendEvent(new Event_BattleStart());
        }


        public void BattleEnd()
        {
            IsBattleStarting = false;
        }


        private void InitUnitsProcess()
        {
            _unitMap.Clear();
            foreach (var entityBehaviour in Global.GetSceneRoot<CharacterRoot>().GetComponentsInChildren<EntityBehaviour>())
            {
                if (entityBehaviour.Entity is not BaseUnit unit) continue;
                _unitMap.Add(unit.Guid, unit);
            }
        }

        public void InitSettleProcess()
        {
            // 关闭输入阻碍
            _blockSequence = false;
            // 当单位死亡时，注销所有其注册的反应
            Global.RegisterEvent<Event_Unit.Death>(OnUnitDeath);

            Players     = new List<BattlePlayer>();
            HumanPlayer = new HumanPlayer {PlayerNumber = UnitCampNumber.PLAYER.ToInt()};
            
            Players.Add(HumanPlayer);
            Players.Add(new AIPlayer());
            
            TurnResolveController = new TurnResolveController();
            TurnResolveController.Init(this);

            var indicatorNode = new GameObject($"{nameof(BattleUI3DNode)}").transform;
            
            BattleUI3DNode = new BattleUI3DNode();
            BattleUI3DNode.OnInit(indicatorNode);

            // 显示战斗UI 
            Global.Get<GUIManager>().JumpPanel(ConstPanelId.BattlePanel);
            BattleCellGrid.OnStartBattle();
            
            var agent = new SettleCursorAgent(this);
            Global.Get<CursorManager>().BindObjects(agent);
        }


        public void CleanUp()
        {
            EventHandler.UnRegisterAll();
            // Global.Get<BattleSystem>().UnRegisterEvent<Event_Unit.Death>(OnUnitDeath);
        }


        private void OnUnitDeath(Event_Unit.Death e) { }


        /// <summary>
        /// 获取所有单位（包括死亡单位）
        /// </summary>
        /// <returns></returns>
        public IEnumerable<BaseUnit> GetAllUnits()
        {
            return _unitMap.Values.Where(Global.Get<BattleSystem>().IsUnitValid);
        }

        public void RemoveUnit(BaseUnit unit) { }


        public IEnumerable<BaseUnit> GetUnitsByPlayer(int number)
        {
            return GetAllUnits().Where(u => u.PlayerNumber == number);
        }


        public IEnumerable<BaseUnit> GetCurrentUnits()
        {
            return GetUnitsByPlayer(this.CurrentPlayer.PlayerNumber);
        }

        #endregion


        #region State

        private GameState _gameState;

        public GameState GameState
        {
            get => _gameState;
            set
            {
                GameState nextState = _gameState == null ? value : _gameState.OnMakeTransition(value);
                GameState lastState = _gameState;
                
                lastState?.StateExit(nextState);
                _gameState = nextState;
                nextState.StateEnter(lastState);
            }
        }


        public void OnEntitySelect(BaseEntity entity)
        {
            GameState?.OnEntitySelectEvent(entity, SelectEventType.SELECT);
        }

        public void OnEntityDeselect(BaseEntity entity)
        {
            GameState?.OnEntitySelectEvent(entity, SelectEventType.DESELECT);
        }

        public void OnEntityHighlight(BaseEntity entity)
        {
            GameState?.OnEntitySelectEvent(entity, SelectEventType.HIGHLIGHT);
        }


        public void OnEntityDeHighlight(BaseEntity entity)
        {
            GameState?.OnEntitySelectEvent(entity, SelectEventType.DE_HIGHLIGHT);
        }

        #endregion


        public void ClearUp() { }
        
        
        private void UnRegister()
        {
            StopAllCoroutines();
            // 注销规则
            // MainArchitecture.Interface.GetModel<RulesModel>()?.ClearRules();
        }
        
        
        public BaseUnit GetUnitByGuid(string guid)
        {
            if (string.IsNullOrEmpty(guid)) return null;
            return this._unitMap.GetValueOrDefault(guid);
        }

        #if UNITY_EDITOR

        private void OnDrawGizmos()
        {
            BattleCellGrid?.OnDrawGizmos();
        }
        #endif
        #region Input Buffer

        private Queue<KeyValuePair<string, IEnumerator>> _inputSequence = new();
        private bool _isPlaying = false;

        /// 阻碍所有的新输入
        private bool _blockSequence = false;

        public void AddSequenceBuffer(string sequenceName, IEnumerator sequence)
        {
            // Debug.Log("输入缓冲队列 + \n" + sequenceName);
            // // 如果处于block状态，不会新增队列
            if (_blockSequence) return;


            _inputSequence.Enqueue(new(sequenceName, sequence));
            // 如果队列不为播放状态（播放队列为空），开启新协程进行播放
            if (!_isPlaying)
            {
                StartCoroutine(StartSequence());
            }
        }

        private IEnumerator StartSequence()
        {
            _isPlaying = true;
            while (_inputSequence.TryDequeue(out var node))
            {
                yield return StartCoroutine(node.Value);
            }

            _isPlaying = false;
        }

        #endregion
    }

    
    
    // public class BattleStartArgs
    // {
    //     public IEnumerable<UnitPrefabEntityConfig> LeftUnits { get; private set; }
    //     public IEnumerable<UnitPrefabEntityConfig> RightUnits { get; private set; }
    //
    //     public BattleStartArgs(IEnumerable<UnitPrefabEntityConfig> leftUnits, IEnumerable<UnitPrefabEntityConfig> rightUnits)
    //     {
    //         LeftUnits = leftUnits;
    //         RightUnits = rightUnits;
    //     }
    // }
    
    public class BattleSequence
    {
        public string SequenceId;
        public IEnumerator SequenceProcess;

        public BattleSequence(string sequenceId, IEnumerator sequenceProcess)
        {
            SequenceId = sequenceId;
            SequenceProcess = sequenceProcess;
        }
    }
}